﻿using System;
using System.Collections.Generic;
using System.Linq;
using Collab.Services.Remote.Contracts;
using Collab.Services.Remote.Entities;

namespace Collab.Services.Remote
{
    public class RemoteCollaborationCallback : IRemoteCollaborationCallback
    {
        private readonly Subject<BufferUpdate> changePublishedSubject = new Subject<BufferUpdate>();
        private readonly Subject<User> userConnectedSubject = new Subject<User>();
        private readonly Subject<User> userDisconnectedSubject = new Subject<User>();
        private readonly Subject<FileChunk> fileChunkReceivedSubject = new Subject<FileChunk>();
        private readonly Subject<UserStatus> userStatusReceivedSubject = new Subject<UserStatus>();
        private readonly Subject<Solution> whenOpenedSolutionSubject = new Subject<Solution>();
        private readonly Subject<AddedFileInformation> whenFileAdded = new Subject<AddedFileInformation>();
        private readonly Subject<FileRequest> whenFileRequested = new Subject<FileRequest>();

        #region IRemoteCollaborationCallback Members

        public IObservable<BufferUpdate> WhenChangeReceived { get { return this.changePublishedSubject.AsObservable(); } }
        public IObservable<User> WhenUserConnected { get { return this.userConnectedSubject.AsObservable(); } }
        public IObservable<User> WhenUserDisconnected { get { return this.userDisconnectedSubject.AsObservable(); } }
        public IObservable<FileChunk> FileChunkReceived { get { return this.fileChunkReceivedSubject.AsObservable(); } }
        public IObservable<UserStatus> WhenUserStatusReceived { get { return this.userStatusReceivedSubject.AsObservable(); } }
        public IObservable<Solution> WhenOpenedSolution { get { return this.whenOpenedSolutionSubject.AsObservable(); } }
        public IObservable<AddedFileInformation> WhenFileAdded { get { return this.whenFileAdded.AsObservable(); } }
        public IObservable<FileRequest> WhenFileRequestReceived { get { return this.whenFileRequested.AsObservable(); } }

        public event Action<string, int> DocumentSynchronized;

        public void RaiseChangePublished(BufferUpdate change)
        {
            this.changePublishedSubject.OnNext(change);
        }

        public void RaiseUserConnected(User user)
        {
            this.userConnectedSubject.OnNext(user);
        }

        public void RaiseUserDisconnected(User user)
        {
            this.userDisconnectedSubject.OnNext(user);
        }

        public void RaisedDocumentSynchronize(string text, int revision)
        {
            if (this.DocumentSynchronized != null)
                this.DocumentSynchronized(text, revision);
        }

        public void RaiseFileChunkReceived(FileChunk fileChunk)
        {
            this.fileChunkReceivedSubject.OnNext(fileChunk);
        }

        #endregion

        public void RaiseUserStatusReceived (UserStatus status)
        {
            this.userStatusReceivedSubject.OnNext(status);
        }

        public void RaiseOpenedSolution(Solution solution)
        {
            this.whenOpenedSolutionSubject.OnNext(solution);
        }


        public void RaiseFileAdded(AddedFileInformation fileInformation)
        {
            this.whenFileAdded.OnNext(fileInformation);
        }

        public void RaiseFileRequested(FileRequest fileRequest)
        {
            this.whenFileRequested.OnNext(fileRequest);
        }
    }
}
